package simpledb.lock;

import simpledb.storage.BufferPool;
import simpledb.storage.PageId;
import simpledb.transaction.TransactionAbortedException;
import simpledb.transaction.TransactionId;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;




public class LockManager {

    // 核心存储：页面→{事务→锁}（仅记录S/X锁）
    private final ConcurrentHashMap<PageId, ConcurrentHashMap<TransactionId, PageLock>> lockMap = new ConcurrentHashMap<>();

    // 反向映射：事务→页面集合（记录事务持有S/X锁的页面）,用于事务结束时快速遍历事务持有锁的页面
    private final ConcurrentHashMap<TransactionId, Set<PageId>> txToPages = new ConcurrentHashMap<>();

    // 表级意向锁存储：表→{事务→意向锁类型（IS/IX）}
    private final ConcurrentHashMap<Integer, ConcurrentHashMap<TransactionId, LockType>> tableIntentLocks = new ConcurrentHashMap<>();

    // 反向映射：事务→表集合（记录事务持有意向锁的表），用于事务结束时释放
    private final ConcurrentHashMap<TransactionId, Set<Integer>> txToTables = new ConcurrentHashMap<>();

    // 锁和条件变量容器
    private static class LockAndCondition {
        // 页/表级别锁（共用一个锁对象保证互斥）
        final ReentrantLock lock = new ReentrantLock();
        // 等待S锁的条件变量
        final Condition sCondition = lock.newCondition();
        // 等待X锁的条件变量
        final Condition xCondition = lock.newCondition();
        int waitXCount = 0; // 写锁等待计数器：记录当前等待X锁的线程数
    }

    // 每个页面一个显式锁，用于控制对页的等待/唤醒
    private final ConcurrentHashMap<PageId, LockAndCondition> pageLocks = new ConcurrentHashMap<>();

    // 每个表一个显式锁，用于控制表级意向锁的等待/唤醒
    private final ConcurrentHashMap<Integer, LockAndCondition> tableLocks = new ConcurrentHashMap<>();

    // 锁兼容性矩阵：[请求锁][现有锁] → 是否兼容
    private static final boolean[][] COMPATIBILITY = {
            // 行：请求锁（IS, IX, S, X）
            // 列：现有锁（IS, IX, S, X）
            {true,  true,  true,  false},  // IS与其他锁的兼容性
            {true,  true,  false, false},  // IX与其他锁的兼容性
            {true,  false, true,  false},  // S与其他锁的兼容性
            {false, false, false, false}   // X与其他锁的兼容性
    };

    // 死锁检测线程
    private final DeadlockDetector deadlockDetector;
    // 死锁检测线程是否正在运行
    public LockManager() {
        this(false, 50, null);
    }

    private final BufferPool bufferPool;

    public LockManager(boolean enableDeadlockDetection, long deadlockCheckInterval, BufferPool bufferPool) {
        this.bufferPool = bufferPool;
        this.deadlockDetector = new DeadlockDetector(enableDeadlockDetection, deadlockCheckInterval, this, bufferPool);
        System.out.println("[LockManager] 初始化锁管理器，死锁检测: " + (enableDeadlockDetection ? "开启" : "关闭"));
    }

    // 添加等待关系（委托给死锁检测器）
    private void addWaitRelation(TransactionId tx, TransactionId waitingForTx) {
        deadlockDetector.addWaitRelation(tx, waitingForTx);
    }

    // 批量添加单向等待关系
    private void addWaitRelations(TransactionId tx, Set<TransactionId> txSet) {
        deadlockDetector.addWaitRelations(tx, txSet);
    }

    // 移除等待关系（委托给死锁检测器）
    private void removeWaitRelations(TransactionId tx) {
        deadlockDetector.removeWaitRelations(tx);
    }

    public void shutdown() {
        // 关闭死锁检测器
        deadlockDetector.shutdown();
    }


    // 被保护在ReentrantLock下，保证互斥（仅处理S/X锁）
    private boolean putLock(TransactionId tid, PageId pageId, LockType requestLock, ConcurrentHashMap<TransactionId, PageLock> txLocks) {
        if (requestLock != LockType.SHARE_LOCK && requestLock != LockType.EXCLUSIVE_LOCK) {
            throw new IllegalArgumentException("页级锁只能是S或X");
        }

        // 当前页没有人加锁，直接创建新的空位
        if (txLocks == null) {
            txLocks = new ConcurrentHashMap<>();
            lockMap.put(pageId, txLocks);
        }

        PageLock pageLock = new PageLock(tid, pageId, requestLock, 1);
        // 放入lockMap
        txLocks.put(tid, pageLock);
        // 将新创建的事务的锁放入对应的页面管理器中
        Set<PageId> pages = txToPages.computeIfAbsent(tid, k ->ConcurrentHashMap.newKeySet());
        boolean added = pages.add(pageId);
        // 打印锁获取成功及事务-页面集合变化
        //System.out.printf("[锁成功] 事务[%s]获取页面[%s]的%s锁 | 事务持有页面变化: 添加后数量为=%d%n",
        //         tid, pageId, requestLock, pages.size());
        return true;
    }

    private boolean handleReentrantLock(PageLock existingLock, LockType requestLock, ConcurrentHashMap<TransactionId, PageLock> txLocks) {
        TransactionId tid = existingLock.getTid();
        PageId pageId = existingLock.getPageId();

        // 锁重入类型相同的时候，直接返回就行
        if (existingLock.getType() == requestLock) {
            ////System.out.printf("[锁重入] 事务[%s]重入获取页面[%s]的%s锁 | 事务持有页面=%s%n",
            //         tid, pageId, requestLock, txToPages.get(tid));
            return true;
        } else if (requestLock == LockType.EXCLUSIVE_LOCK && existingLock.getType() == LockType.SHARE_LOCK) {
            // 若只有当前事务持有锁，可以升级
            if (txLocks.size() == 1) {
                existingLock.setType(LockType.EXCLUSIVE_LOCK);
                //System.out.printf("[锁升级] 事务[%s]将页面[%s]的S锁升级为X锁 | 事务持有页面=%d%n",
                //         tid, pageId, txToPages.get(tid).size());
                return true;
            } else {
                //System.out.printf("[锁升级失败] 事务[%s]无法将页面[%s]的S锁升级为X锁，当前有%d个事务持有锁%n",
                //         tid, pageId, txLocks.size());
                return false;
            }
        } else if (requestLock == LockType.SHARE_LOCK && existingLock.getType() == LockType.EXCLUSIVE_LOCK) {
            //System.out.printf("[锁降级] 事务[%s]将页面[%s]的X锁降级为S锁 | 事务持有页面=%d%n",
            //         tid, pageId, txToPages.get(tid).size());
            return true;
        }
        return false;
    }

    // 判断请求的锁类型和当前锁是否兼容
    private boolean isCompatible(LockType request, LockType existing) {
        int reqIdx = getLockIndex(request);
        int existIdx = getLockIndex(existing);
        return COMPATIBILITY[reqIdx][existIdx];
    }

    // 获取锁类型的index用于对比
    private int getLockIndex(LockType type) {
        return switch (type) {
            case INTENTION_SHARE_LOCK -> 0;
            case INTENTION_EXCLUSIVE_LOCK -> 1;
            case SHARE_LOCK -> 2;
            case EXCLUSIVE_LOCK -> 3;
            default -> throw new IllegalArgumentException("未知锁类型");
        };
    }

    // 要插入的锁是否与当前页面中其他锁兼容
    private boolean isCompatibleWithAll(PageId pageId, LockType requestLock, TransactionId tid) {
        ConcurrentHashMap<TransactionId, PageLock> txLocks = lockMap.get(pageId);
        // 还没有其他人持有当前的锁，可以插入
        if (txLocks == null) return true;

        for (Map.Entry<TransactionId, PageLock> entry : txLocks.entrySet()) {
            TransactionId existingTid = entry.getKey();
            LockType existingLock = entry.getValue().getType();
            // 如果持有者是自己，跳过对比
            if (existingTid.equals(tid)) continue;
            // 检查sx锁是否存在不兼容
            if (!isCompatible(requestLock, existingLock)) {
                //System.out.printf("[锁冲突] 事务[%s]请求页面[%s]的%s锁，与事务[%s]持有的%s锁不兼容%n",
                //         tid, pageId, requestLock, existingTid, existingLock);
                return false;
            }
        }
        return true;
    }

    // 检查是否持有目标类型的表级意向锁
    private boolean holdsTableIntentionLock(TransactionId tid, Integer tableId, LockType type) {
        ConcurrentHashMap<TransactionId, LockType> txLocks = tableIntentLocks.get(tableId);
        if (txLocks == null) return false;
        LockType heldType = txLocks.get(tid);
        return heldType != null && heldType == type;
    }

    private boolean isValidUpgrade(LockType from, LockType to) {
        // 允许的升级路径：S→X（页级）；IS→IX（表级意向锁）
        return (from == LockType.SHARE_LOCK && to == LockType.EXCLUSIVE_LOCK) ||
                (from == LockType.INTENTION_SHARE_LOCK && to == LockType.INTENTION_EXCLUSIVE_LOCK);
    }

    // 获取表级意向锁（简化版：系统中仅存在IS和IX锁）
    private boolean acquireTableIntentionLock(Integer tableId, TransactionId tid, LockType intentLock,
                                              long timeout, long interval) throws TransactionAbortedException, InterruptedException {
        // 验证意向锁类型，只能是IS或IX
        if (intentLock != LockType.INTENTION_SHARE_LOCK && intentLock != LockType.INTENTION_EXCLUSIVE_LOCK) {
            throw new IllegalArgumentException("只能获取IS或IX类型的表级意向锁");
        }

        long start = System.currentTimeMillis();
        LockAndCondition tableLock = tableLocks.computeIfAbsent(tableId, k -> new LockAndCondition());
        Condition condition = tableLock.sCondition;

        while (true) {
            try {
                tableLock.lock.lock();
                long elapsed = System.currentTimeMillis() - start;
                if (elapsed > timeout) {
                    String msg = String.format("[表锁超时] 事务[%s]获取表[%d]的%s锁超时（%dms）",
                            tid, tableId, intentLock, timeout);
                    // System.out.println(msg);
                    throw new TransactionAbortedException(msg);
                }

                ConcurrentHashMap<TransactionId, LockType> txLocks = tableIntentLocks.computeIfAbsent(tableId, k -> new ConcurrentHashMap<>());
                LockType existingLock = txLocks.get(tid);

                // 1. 重入处理：已持有相同类型的意向锁
                if (existingLock == intentLock) {
                    //System.out.printf("[表锁重入] 事务[%s]重入获取表[%d]的%s锁 | 事务持有表=%d%n",
                    //         tid, tableId, intentLock, txToTables.get(tid).size());
                    return true;
                }

                // 2. IS→IX升级处理：直接升级（IX与所有意向锁兼容）
                if (existingLock == LockType.INTENTION_SHARE_LOCK && intentLock == LockType.INTENTION_EXCLUSIVE_LOCK) {
                    txLocks.put(tid, intentLock);
                    Set<Integer> tables = txToTables.computeIfAbsent(tid, k -> new HashSet<>());
                    tables.add(tableId);
                    //System.out.printf("[表锁升级] 事务[%s]将表[%d]的IS锁升级为IX锁 | 事务持有表=%d%n",
                    //         tid, tableId, tables.size());
                    return true;
                }

                // 3. 新获取意向锁：无需检查兼容性（IS/IX与现有意向锁必然兼容）
                if (existingLock == null) {
                    txLocks.put(tid, intentLock);
                    Set<Integer> tables = txToTables.computeIfAbsent(tid, k -> new HashSet<>());
                    tables.add(tableId);
                    //System.out.printf("[表锁成功] 事务[%s]获取表[%d]的%s锁 | 事务持有表=%d%n",
                    //         tid, tableId, intentLock, tables.size());
                    return true;
                }

                // 4. 无法获取锁（仅可能是已有其他类型锁，如并发升级冲突）
                long remaining = timeout - elapsed;
                if (remaining <= 0) {
                    String msg = String.format("[表锁超时] 事务[%s]获取表[%d]的%s锁超时（%dms）",
                            tid, tableId, intentLock, timeout);
                    // System.out.println(msg);
                    throw new TransactionAbortedException(msg);
                }
                //System.out.printf("[表锁等待] 事务[%s]等待表[%d]的%s锁（已有%s锁），剩余等待时间：%dms%n",
                //         tid, tableId, intentLock, existingLock, remaining);
                condition.await(Math.min(remaining, interval), TimeUnit.MILLISECONDS);
            } finally {
                if (tableLock.lock.isHeldByCurrentThread()) {
                    tableLock.lock.unlock();
                }
            }
        }
    }

    private boolean acquireIntentionLockIfNeed(PageId pageId, TransactionId tid, LockType targetLock, long timeout, long interval)
            throws TransactionAbortedException, InterruptedException {
        // 仅S/X锁需要表级意向锁
        if (targetLock == LockType.INTENTION_SHARE_LOCK || targetLock == LockType.INTENTION_EXCLUSIVE_LOCK) {
            return true;
        }

        Integer tableId = pageId.getTableId();

        // 获取S锁前需持有表的IS或IX
        if (targetLock == LockType.SHARE_LOCK) {
            if (!holdsTableIntentionLock(tid, tableId, LockType.INTENTION_SHARE_LOCK) &&
                    !holdsTableIntentionLock(tid, tableId, LockType.INTENTION_EXCLUSIVE_LOCK)) {
                return acquireTableIntentionLock(tableId, tid, LockType.INTENTION_SHARE_LOCK, timeout, interval);
            }
        }

        // 获取X锁前需持有表的IX
        if (targetLock == LockType.EXCLUSIVE_LOCK) {
            if (!holdsTableIntentionLock(tid, tableId, LockType.INTENTION_EXCLUSIVE_LOCK)) {
                if (holdsTableIntentionLock(tid, tableId, LockType.INTENTION_SHARE_LOCK)) {
                    // 升级IS→IX
                    return acquireTableIntentionLock(tableId, tid, LockType.INTENTION_EXCLUSIVE_LOCK, timeout, interval);
                } else {
                    // 直接获取IX
                    return acquireTableIntentionLock(tableId, tid, LockType.INTENTION_EXCLUSIVE_LOCK, timeout, interval);
                }
            }
        }
        return true;
    }

    public boolean acquireLock(PageId pageId, TransactionId tid, LockType requestLock,
                               long timeout, long interval) throws TransactionAbortedException, InterruptedException {
        // 页级只允许S/X锁
        if (requestLock != LockType.SHARE_LOCK && requestLock != LockType.EXCLUSIVE_LOCK) {
            throw new IllegalArgumentException("页级锁只能获取S或X");
        }

        // 获取所需的表级意向锁
        if (!acquireIntentionLockIfNeed(pageId, tid, requestLock, timeout, interval)) {
            //System.out.printf("[锁失败] 事务[%s]获取页面[%s]的%s锁前，表级意向锁获取失败%n",
            //         tid, pageId, requestLock);
            return false;
        }

        long start = System.currentTimeMillis();

        while (true) {
            // 每次循环重新获取页锁对象（避免持有旧锁）
            LockAndCondition pageLock = pageLocks.computeIfAbsent(pageId, k -> new LockAndCondition());

            try {
                pageLock.lock.lock();

                // 首先检查事务是否已被中止（在锁保护下检查）
                // 此时有两种情况,一种是死锁检查发现死锁的回滚在前, 此时 由于标记为所以不会再继续获取锁
                // 另一种检查完了,死锁才回滚事务,但是由于页面锁,回滚必然发生在当前获取锁之后,获取了也没影响.
                if (bufferPool!=null && bufferPool.isTransactionAborted(tid)) {
                    throw new TransactionAbortedException("事务" + tid + "已被死锁检测器中止");
                }

                // 验证：当前锁是否已被从pageLocks中删除
                if (pageLocks.get(pageId) != pageLock) {
                    //System.out.printf("[锁失效] 页面[%s]的锁对象已被清理，重新获取%n", pageId);
                    continue; // 重新循环获取新锁
                }
                long elapsed = System.currentTimeMillis() - start;
                if (elapsed > timeout) {
                    String msg = String.format("[锁超时] 事务[%s]获取页面[%s]的%s锁超时（%dms）",
                            tid, pageId, requestLock, timeout);
                    // System.out.println(msg);
                    throw new TransactionAbortedException(msg);
                }

                ConcurrentHashMap<TransactionId, PageLock> txLocks = lockMap.computeIfAbsent(pageId, k -> new ConcurrentHashMap<>());
                PageLock existingLock = txLocks.get(tid);

                // 处理重入
                if (existingLock != null) {
                    if (existingLock.getType() == requestLock) {
                        return true; // 已在handleReentrantLock中打印
                    }
                    // 尝试升级
                    if (isValidUpgrade(existingLock.getType(), requestLock)) {
                        if (isCompatibleWithAll(pageId, requestLock, tid)) {
                            boolean success = handleReentrantLock(existingLock, requestLock, txLocks);
                            if (!success) {
                                //System.out.printf("[锁升级失败] 事务[%s]升级页面[%s]的%s→%s锁失败%n",
                                //         tid, pageId, existingLock.getType(), requestLock);
                            }
                            return success;
                        } else {
                            //System.out.printf("[锁升级冲突] 事务[%s]升级页面[%s]的%s→%s锁时存在冲突锁%n",
                            //         tid, pageId, existingLock.getType(), requestLock);
                        }
                    } else {
                        //System.out.printf("[锁类型错误] 事务[%s]无法将页面[%s]的%s锁转换为%s锁（不支持的转换）%n",
                        //         tid, pageId, existingLock.getType(), requestLock);
                    }
                }

                // 新锁请求：读锁需要额外检查是否有写锁等待
                boolean canAcquire = false;
                if (requestLock == LockType.SHARE_LOCK) {
                    // 读锁需满足：与现有锁兼容 + 无写锁等待
                    canAcquire = isCompatibleWithAll(pageId, requestLock, tid) && pageLock.waitXCount == 0;
                    if (!canAcquire) {
                        if (pageLock.waitXCount > 0) {
                            //System.out.printf("[锁等待] 事务[%s]请求页面[%s]的S锁，但存在%d个写锁等待，需排队%n",
                            //         tid, pageId, pageLock.waitXCount);
                        }
                    }
                } else {
                    // 写锁只需满足与现有锁兼容
                    canAcquire = isCompatibleWithAll(pageId, requestLock, tid);
                }

                if (canAcquire) {
                    return putLock(tid, pageId, requestLock, txLocks); // 已在putLock中打印
                }

                // 等待唤醒
                long remaining = timeout - elapsed;
                if (remaining <= 0) {
                    String msg = String.format("[锁超时] 事务[%s]获取页面[%s]的%s锁超时（%dms）",
                            tid, pageId, requestLock, timeout);
                    // System.out.println(msg);
                    throw new TransactionAbortedException(msg);
                }

                // 只有获得锁失败的时候需要添加等待关系图,如果是写等待读，那么等待事务中不会有新的事务出现，因为约束了有写等待的时候
                // 不会进入新的读。
                // 同理，如果是读等待写，同一时间只可能有一个写，此时也不可能，换新的
                // 但是万一并发,导致这中间持有锁的人变了,所以需要重新添加.
                // 收集当前持有锁的其他事务（等待关系的目标）并添加到等待图中
                // 批量添加等待关系，减少锁获取次数
                addWaitRelations(tid, txLocks.keySet());

                //System.out.printf("[锁等待] 事务[%s]等待页面[%s]的%s锁，剩余等待时间：%dms | 当前持有锁的事务数：%d%n",
                //         tid, pageId, requestLock, remaining, txLocks.size());

                if (requestLock == LockType.SHARE_LOCK) {
                    // 等待S锁的线程进入sCondition队列
                    pageLock.sCondition.await(Math.min(remaining, interval), TimeUnit.MILLISECONDS);
                } else {
                    // 写锁等待前先增加计数器，避免新读锁插入
                    pageLock.waitXCount++;
                    try {
                        pageLock.xCondition.await(Math.min(remaining, interval), TimeUnit.MILLISECONDS);
                    } finally {
                        pageLock.waitXCount--; // 唤醒后减少计数器
                    }
                }
            } finally {
                if (pageLock.lock.isHeldByCurrentThread()) {
                    pageLock.lock.unlock();
                }
            }
        }
    }

    private void handleRelease(PageLock existingLock, LockType releaseType, ConcurrentHashMap<TransactionId, PageLock> txLocks) {
        TransactionId tid = existingLock.getTid();
        PageId pageId = existingLock.getPageId();

        existingLock.setCount(0);
        if (existingLock.getCount() <= 0) {
            txLocks.remove(tid);
            Set<PageId> pages = txToPages.get(tid);
            if (pages != null) {
                pages.remove(pageId);
                //System.out.printf("[锁释放] 事务[%s]释放页面[%s]的%s锁 | 事务持有页面变化: 移除后=%d%n",
                //         tid, pageId, releaseType, pages.size());
            }
        } else {
            //System.out.printf("[锁计数减少] 事务[%s]减少页面[%s]的%s锁计数（剩余：%d）%n",
            //         tid, pageId, releaseType, existingLock.getCount());
        }
    }

    public void releasePage(TransactionId tid, PageId pid) {
        LockAndCondition pageLock = pageLocks.get(pid);
        if (pageLock == null) {
            //System.out.printf("[释放无效] 事务[%s]尝试释放页面[%s]的锁，但该页面无锁记录%n", tid, pid);
            return;
        }

        try {
            pageLock.lock.lock();
            // 再次检查pageLocks中是否仍为当前锁（防止刚获取锁就被删除）
            // 这个其实多余检查，但是防御性变成
            if (pageLocks.get(pid) != pageLock) {
                //System.out.printf("[释放无效] 页面[%s]的锁已被清理，无需释放%n", pid);
                return;
            }
            ConcurrentHashMap<TransactionId, PageLock> txLocks = lockMap.get(pid);
            if (txLocks == null) {
                //System.out.printf("[释放无效] 事务[%s]尝试释放页面[%s]的锁，但锁映射中无该页面%n", tid, pid);
                return;
            }

            PageLock lock = txLocks.get(tid);
            if (lock == null) {
                //System.out.printf("[释放无效] 事务[%s]未持有页面[%s]的锁，释放失败%n", tid, pid);
                return;
            }

            // 处理页级锁释放
            handleRelease(lock, lock.getType(), txLocks);

            // 清理空资源
            boolean isEmpty = txLocks.isEmpty();
            if (isEmpty) {
                lockMap.remove(pid);
                pageLocks.remove(pid);
                //System.out.printf("[资源清理] 页面[%s]已无锁持有，清理相关资源%n", pid);
            }

            // 唤醒策略：优先唤醒写锁（若有等待），否则唤醒读锁
            if (isEmpty) {
                // 页面无锁：优先唤醒写锁，再唤醒读锁
                pageLock.xCondition.signalAll();
                pageLock.sCondition.signalAll();
                //System.out.printf("[唤醒通知] 页面[%s]无锁，唤醒所有等待的读写锁%n", pid);
            } else {
                // 检查是否有写锁等待，优先唤醒
                if (pageLock.waitXCount > 0) {
                    pageLock.xCondition.signalAll();
                    //System.out.printf("[唤醒通知] 页面[%s]有%d个写锁等待，优先唤醒写锁%n", pid, pageLock.waitXCount);
                } else {
                    // 无写锁等待时唤醒读锁
                    pageLock.sCondition.signalAll();
                    //System.out.printf("[唤醒通知] 页面[%s]无写锁等待，唤醒所有读锁%n", pid);
                }
            }
        } finally {
            if (pageLock.lock.isHeldByCurrentThread()) {
                pageLock.lock.unlock();
            }
        }
    }

    // 释放表级意向锁
    private void releaseTableIntentionLock(TransactionId tid, Integer tableId) {
        LockAndCondition tableLock = tableLocks.get(tableId);
        if (tableLock == null) {
            //System.out.printf("[表锁释放无效] 事务[%s]尝试释放表[%d]的意向锁，但该表无锁记录%n", tid, tableId);
            return;
        }

        try {
            tableLock.lock.lock();
            ConcurrentHashMap<TransactionId, LockType> txLocks = tableIntentLocks.get(tableId);
            if (txLocks == null) {
                //System.out.printf("[表锁释放无效] 事务[%s]尝试释放表[%d]的意向锁，但锁映射中无该表%n", tid, tableId);
                return;
            }

            LockType releasedLock = txLocks.remove(tid);
            if (releasedLock != null) {
                Set<Integer> tables = txToTables.get(tid);
                if (tables != null) {
                    tables.remove(tableId);
                    //System.out.printf("[表锁释放] 事务[%s]释放表[%d]的%s锁 | 事务持有表变化: 移除后=%s%n",
                    //         tid, tableId, releasedLock, tables);
                }
            } else {
                //System.out.printf("[表锁释放无效] 事务[%s]未持有表[%d]的意向锁，释放失败%n", tid, tableId);
            }

            if (txLocks.isEmpty()) {
                tableIntentLocks.remove(tableId);
                tableLocks.remove(tableId);
                //System.out.printf("[表锁资源清理] 表[%d]已无意向锁持有，清理相关资源%n", tableId);
            }

            tableLock.sCondition.signalAll();
            //System.out.printf("[表锁唤醒] 表[%d]释放锁后，唤醒等待线程%n", tableId);
        } finally {
            tableLock.lock.unlock();
        }
    }

    public void releaseAllLocks(TransactionId tid) {
        // 释放所有页级锁
        Set<PageId> pages = txToPages.get(tid);
        if (pages != null) {
            List<PageId> pagesCopy = new ArrayList<>(pages);
            //System.out.printf("[释放所有锁] 事务[%s]开始释放%d个页级锁：%s%n", tid, pagesCopy.size(), pagesCopy);
            pagesCopy.forEach(pid -> releasePage(tid, pid));
            txToPages.remove(tid);
        } else {
            //System.out.printf("[释放所有锁] 事务[%s]无页级锁可释放%n", tid);
        }

        // 释放所有表级意向锁
        Set<Integer> tables = txToTables.get(tid);
        if (tables != null) {
            List<Integer> tablesCopy = new ArrayList<>(tables);
            //System.out.printf("[释放所有表锁] 事务[%s]开始释放%d个表级意向锁：%s%n", tid, tablesCopy.size(), tablesCopy);
            tablesCopy.forEach(tableId -> releaseTableIntentionLock(tid, tableId));
            txToTables.remove(tid);
        } else {
            //System.out.printf("[释放所有表锁] 事务[%s]无表级意向锁可释放%n", tid);
        }
        // 释放锁后清除等待关系
        removeWaitRelations(tid);
    }
}